//
//  GameController.cpp
//  ;
//
//  Created by USoft on 6/3/14.
//
//

#include "GameController.h"
GameController::GameController() {
    this->gameModel = GameModel::getInstance();
    this->director = Director::getInstance();
    this->soundModel = SoundModel::getInstance();
    this->registerHandler(1, this, ug_handler_func(GameController::processEvent));
    this->registerHandlerByEventType(EVT_CLICK_BUTTON, 0, this, ug_handler_func(GameController::processButtonSoundEffect));
}

GameController::~GameController(void) {
    Utils::safeRelease(this->director);
    Utils::safeRelease(this->gameModel);
    Utils::safeRelease(this->soundModel);
}

void GameController::processButtonSoundEffect(UGEvent* event){
    this->soundModel->playEffect(EF_BUTTON,false,0.0f);
}

void GameController::processEvent(UGEvent* event) {
    if (event->getId() == REQ_BEGIN_GAME) {
        Scene* homeScene = HomeScene::create();
        this->director->runWithScene(homeScene);
        this->soundModel->playBackgroundMusic(BG_MUSIC_HOME, true, 0.0f, 0.0f);
    }
    
    if (event->getId() == REQ_GAME_MODE) {
        this->soundModel->playBackgroundMusic(BG_MUSIC_GAME, true, 0.0f, 0.0f);
        Scene* gameScene = GameScene::create();
        this->director->replaceScene(gameScene);
        return;
    }
    
    if (event->getId() == REQ_COIN_APPEAR) {
        this->gameModel->handTouching();
        return;
    }
    
    if (event->getId() == REQ_PAUSE) {
        this->gameModel->setGameState(GS_PAUSE);
    }
    
    if (event->getId() == REQ_UPGRADE) {
        this->gameModel->setGameState(GS_UPGRADE);
        return;
    }
    if (event->getId() == REQ_EFFECT_APPEAR) {
        Point point = *(Point*) (((UGDefaultEvent*) event)->getArg());
        this->gameModel->effectAppear(point);
    }
    if (event->getId() == REQ_RESUME) {
        this->gameModel->setGameState(GS_PLAY);
        return;
    }
    
    if (event->getId() == REQ_ACHIEVEMENT) {
        this->gameModel->setGameState(GS_ACHIEVEMENT);
    }
    
    if (event->getId() == REQ_CONVERSION) {
        this->gameModel->setGameState(GS_CONVERSION);
    }
    
    if (event->getId() == REQ_OPTION) {
        this->gameModel->setGameState(GS_OPTION);
    }
    
    if (event->getId() == REQ_STATS) {
        this->gameModel->setGameState(GS_STATISTICS);
    }
    
    if (event->getId() == REQ_SHOPPING) {
        this->gameModel->setGameState(GS_SHOPPING);
    }
    if (event->getId() == REQ_UPGRADE_FINGER) {
        Finger* finger = this->gameModel->getFinger();
        FingerInformation* fingerInfo = this->gameModel->getFingerInformation();
        BigNumber* cost = finger->getCost();
        BigNumber* currentAmount = this->gameModel->getScore();
        if (cost->compare(currentAmount) <= 0) {
            this->gameModel->subMoney(cost);
            finger->upLevel(fingerInfo, finger->getLevel() + 1, finger->getUpgradeLevel(), this->gameModel->getTotalCharactersLevel());
        }
    }
    
    if (event->getId() == REQ_SPECIAL_UPGRADE_FINGER) {
        Finger* finger = this->gameModel->getFinger();
        FingerInformation* fingerInfo = this->gameModel->getFingerInformation();
        FingerUpgrade* fingerUpgrade = NULL;
        int newUpgradeLevel = finger->getUpgradeLevel() + 1;
        if (newUpgradeLevel < fingerInfo->getUpgradeInfo()->count()) {
            fingerUpgrade = (FingerUpgrade*)fingerInfo->getUpgradeInfo()->getObjectAtIndex(newUpgradeLevel);
        }
        int currentLevel = finger->getLevel();
        int requiredLevel = fingerUpgrade->getRequiredLevel();
        if (fingerUpgrade != NULL && currentLevel >= requiredLevel) {
            BigNumber *cost = BigNumber::create();
            char* priceString = fingerUpgrade->getPrice()->toString();
            cost->initialize(priceString);
            delete[] priceString;
            BigNumber *currentAmount = BigNumber::create();
            char* amountString = this->gameModel->getScore()->toString();
            currentAmount->initialize(amountString);
            delete[] amountString;
            if (cost->compare(currentAmount)<=0) {
                this->gameModel->subMoney(cost);
                finger->upLevel(fingerInfo, finger->getLevel(), finger->getUpgradeLevel() + 1 , this->gameModel->getTotalCharactersLevel());
                finger->setTimeToNextUpgrade(fingerUpgrade->getTimeWaiting());
            }
        }
    }
    if (event->getId() == REQ_UPGRADE_BONUS_FINGER) {
        Finger* finger = this->gameModel->getFinger();
        FingerInformation* fingerInfo = this->gameModel->getFingerInformation();
        FingerBonus* fingerBonus = NULL;
        int newBonusLevel = finger->getBonusLevel() + 1;
        if (newBonusLevel <= fingerInfo->getBonusInfo()->count()) {
            fingerBonus = (FingerBonus*)fingerInfo->getBonusInfo()->getObjectAtIndex(newBonusLevel - 1);
        }
        if (fingerBonus != NULL) {
            BigNumber *cost = BigNumber::create();
            char* priceString = fingerBonus->getPrice()->toString();
            cost->initialize(priceString);
            delete[] priceString;
            BigNumber *currentAmount = BigNumber::create();
            char* amountString = this->gameModel->getScore()->toString();
            currentAmount->initialize(amountString);
            delete[] amountString;
            if (cost->compare(currentAmount)<=0) {
                this->gameModel->subMoney(cost);
                finger->setBonusLevel(finger->getBonusLevel() + 1);
            }
        }
    }
    
    if (event->getId() == REQ_UPGRADE_BONUS_ATM) {
        Atm* atm = this->gameModel->getAtm();
        AtmInformation* atmInfo = this->gameModel->getAtmInformation();
        AtmBonus* atmBonus = NULL;
        int newBonusLevel = atm->getBonusLevel() + 1;
        if (newBonusLevel < atmInfo->getBonusInfo()->count()) {
            atmBonus = (AtmBonus*)atmInfo->getBonusInfo()->getObjectAtIndex(newBonusLevel);
        }
        if (atmBonus != NULL) {
            BigNumber *cost = BigNumber::create();
            char* priceString = atmBonus->getPrice()->toString();
            cost->initialize(priceString);
            delete[] priceString;
            BigNumber *currentAmount = BigNumber::create();
            char* amountString = this->gameModel->getScore()->toString();
            currentAmount->initialize(amountString);
            delete[] amountString;
            if (cost->compare(currentAmount)<=0) {
                this->gameModel->subMoney(cost);
                atm->setBonusLevel(atm->getBonusLevel() + 1);
                this->gameModel->fireUpgradeAtmFace();
            }

        }
    }
    
    if (event->getId() == REQ_UPGRADE_CHARACTER) {
        __Integer* characterId = (__Integer*) (((UGDefaultEvent*) event)->getArg());
        Character* character = (Character*) gameModel->getCharacters()->objectForKey(characterId->getValue());
        EntityCharacter* ettCharacter = (EntityCharacter*) gameModel->getEttRepository()->getCharacterList()->objectForKey(characterId->getValue());
        EntityCharacterAvatar* ettCharacterAvatar = (EntityCharacterAvatar*) ettCharacter->getAvatars()->getObjectAtIndex(character->getUpgradeLevel());
        if (character != NULL) {
            BigNumber* cost = character->getCost();
            BigNumber* currentAmount = this->gameModel->getScore();
            if (cost->compare(currentAmount)<=0) {
                this->gameModel->subMoney(cost);
                character->upLevel(ettCharacter, character->getNextLevel(),character->getUpgradeLevel());
                gameModel->getFinger()->upLevel(this->gameModel->getFingerInformation(),this->gameModel->getFinger()->getLevel(),this->gameModel->getFinger()->getUpgradeLevel(),this->gameModel->getTotalCharactersLevel());
                if (character->getLevel() == 1) {
                    character->setTimeToNextUpgrade(ettCharacterAvatar->getTimeWaiting());
                }
                if(character->getCharacterId() == CHAR_GAME_DEV && character->getLevel() == 1){
                    char time[100];
                    sprintf(time, "%lf", this->gameModel->getCounter()->getTimePlay());
                    __String* timeString = __String::create(time);
                    __Dictionary* dict = __Dictionary::create();
                    dict->setObject(timeString, "Time");
                    AnalyticX::flurryLogEventWithParameters("GameDev", dict);
                }
            }
           
        }
    }

    if (event->getId() == REQ_SPECIAL_UPGRADE_CHARACTER) {
        __Integer* characterId = (__Integer*) (((UGDefaultEvent*) event)->getArg());
        Character* character = (Character*) gameModel->getCharacters()->objectForKey(characterId->getValue());
        EntityCharacter* ettCharacter = (EntityCharacter*) gameModel->getEttRepository()->getCharacterList()->objectForKey(characterId->getValue());
        EntityCharacterAvatar* ettCharacterAvatar = NULL;
        int newUpgradeLevel = character->getUpgradeLevel() + 1;
        if (newUpgradeLevel < ettCharacter->getAvatars()->count()) {
            ettCharacterAvatar = (EntityCharacterAvatar*) ettCharacter->getAvatars()->getObjectAtIndex(newUpgradeLevel);
        }
        int currentLevel = character->getLevel();
        int requiredLevel = ettCharacterAvatar->getRequiredLevel();
        
        if (ettCharacterAvatar != NULL && currentLevel >= requiredLevel) {
            BigNumber *cost = BigNumber::create();
            char* priceString = ettCharacterAvatar->getPrice()->toString();
            cost->initialize(priceString);
            delete[] priceString;
            BigNumber *currentAmount = BigNumber::create();
            char* amountString = this->gameModel->getScore()->toString();
            currentAmount->initialize(amountString);
            delete[] amountString;
            if (cost->compare(currentAmount)<=0) {
                this->gameModel->subMoney(cost);
                character->upLevel(ettCharacter, currentLevel, newUpgradeLevel);
                character->setTimeToNextUpgrade(ettCharacterAvatar->getTimeWaiting());
            }
        }
    }
    
    if (event->getId() == REQ_CHANGE_CHARACTER) {
        this->gameModel->fireChangeCharacter();
    }
    
    if (event->getId() == REQ_CHANGE_AVATAR_SHOPPING) {
        this->gameModel->fireChangeAvatarShopping();
    }
    
    if (event->getId() == REQ_REVEAL_ACHIVEMENT) {
        __Integer* achievementId = (__Integer*) (((UGDefaultEvent*) event)->getArg());
        AbstractAchievement* achievement = (AbstractAchievement*) this->gameModel->getAchievements()->getObjectAtIndex(achievementId->getValue());
        char* billionString = new char[10];
        sprintf(billionString, "%s", "1000000000");
        BigNumber* aBillion = BigNumber::create();
        aBillion->initialize(billionString);
        delete[] billionString;
        if(this->gameModel->getScore()->compare(aBillion)>=0){
            achievement->setStatus(NUM_STATUS_BOUGHT);
            this->gameModel->subMoney(aBillion);
        }
        this->gameModel->saveStatusAchievement();
    }
    
    if (event->getId() == REQ_REMOVE_NOTIFICATION) {
        __Integer* characterId = (__Integer*) (((UGDefaultEvent*) event)->getArg());
        if (characterId->getValue() == CHAR_ATM) {
            this->gameModel->getAtm()->setHasNotiBonus(false);
        }
        else if (characterId->getValue() == CHAR_FINGER) {
            this->gameModel->getFinger()->setHasNoti(false);
        } else {
            Character* character = (Character*) gameModel->getCharacters()->objectForKey(characterId->getValue());
            character->setHasNoti(false);
        }
        this->gameModel->fireRemoveNotification(characterId->getValue());
    }
    
    if (event->getId() == REQ_REMOVE_BONUS_NOTIFICATION) {
        __Integer* avatarId = (__Integer*) (((UGDefaultEvent*) event)->getArg());
        if (avatarId->getValue() == CHAR_FINGER) {
            this->gameModel->getFinger()->setHasNotiBonus(false);
        } else if(avatarId->getValue() == CHAR_ATM){
            this->gameModel->getAtm()->setHasNotiBonus(false);        }
        this->gameModel->fireRemoveBonusNotification(avatarId->getValue());
    }
    
    if (event->getId() == REQ_SKIP_FINGER) {
//        BigNumber* tempCost = (BigNumber*) (((UGDefaultEvent*) event)->getArg());
        __Dictionary* dict = (__Dictionary*)(((UGDefaultEvent*) event)->getArg());
        BigNumber* tempCost = (BigNumber*)dict->objectForKey("price");
        __Integer* idInt = (__Integer*)dict->objectForKey("id");
        BigNumber *currentAmount = BigNumber::create();
        char* amountString = this->gameModel->getScore()->toString();
        currentAmount->initialize(amountString);
        delete[] amountString;
        
        Finger* finger = this->gameModel->getFinger();
        if(currentAmount->compare(tempCost) >= 0) {
            this->gameModel->subMoney(tempCost);
            finger->setTimeToNextUpgrade(0);
        }
        Utils::safeRelease(tempCost);
    }
    
    if (event->getId() == REQ_SKIP_CHARACTER) {
        __Dictionary* dict = (__Dictionary*)(((UGDefaultEvent*) event)->getArg());
        BigNumber* tempCost = (BigNumber*)dict->objectForKey("price");
        __Integer* idInt = (__Integer*)dict->objectForKey("id");
        
        BigNumber *currentAmount = BigNumber::create();
        char* amountString = this->gameModel->getScore()->toString();
        currentAmount->initialize(amountString);
        delete[] amountString;
        
        Character* character = (Character*)this->gameModel->getCharacters()->objectForKey(idInt->getValue());
        if(currentAmount->compare(tempCost) >= 0) {
            this->gameModel->subMoney(tempCost);
            character->setTimeToNextUpgrade(0);
        }
        Utils::safeRelease(tempCost);
    }

}


